package com.yanqu.road.server.gameplayer.module.activity.xiaowuRecall;

import com.yanqu.road.entity.activity.ActivityInfo;
import com.yanqu.road.entity.activity.xiaowuRecall.XiaowuRecallComb;
import com.yanqu.road.entity.activity.xiaowuRecall.XiaowuRecallUserData;
import com.yanqu.road.entity.activity.xiaowuRecall.config.XiaowuConfig;
import com.yanqu.road.entity.enums.eGamePlayerEventType;
import com.yanqu.road.entity.enums.eLogMoneyType;
import com.yanqu.road.entity.enums.eSystemId;
import com.yanqu.road.entity.log.LogXiaowuRecallDraw;
import com.yanqu.road.entity.log.LogXiaowuRecallReward;
import com.yanqu.road.logic.bussiness.activity.XiaowuRecallBusiness;
import com.yanqu.road.pb.activity.XiaowuRecallProto;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.base.GeneralModule;
import com.yanqu.road.server.gameplayer.module.player.CurrencyModule;
import com.yanqu.road.server.manger.activity.ActivityMgr;
import com.yanqu.road.server.manger.activity.xiaowuRecall.XiaowuRecallMgr;
import com.yanqu.road.server.manger.config.SystemOpenMgr;
import com.yanqu.road.server.manger.log.AutoLogMgr;
import com.yanqu.road.server.manger.log.LogMgr;
import com.yanqu.road.server.pb.XiaowuRecallPb;
import com.yanqu.road.server.protocol.ClientProtocol;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.property.PropertyHelper;
import com.yanqu.road.utils.string.StringUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

import static com.yanqu.road.server.pb.XiaowuRecallPb.createDataMsgBuilder;

public class XiaowuRecallModule extends GeneralModule {

    private XiaowuRecallUserData userData;

    public static int ARRAYNUM_ADD_TO_CELLID = 300001;      //代码用0-15表示格子，配置表用300001到3000016表示

    public XiaowuRecallModule(GamePlayer player) {
        super(player);
    }

    @Override
    public boolean loadData() {
        ActivityInfo activityInfo = XiaowuRecallMgr.getActivityInfo();
        if (ActivityMgr.activityInShowTime(activityInfo)) {
            userData = XiaowuRecallBusiness.getXiaowuRecallUserData(activityInfo.getActivityId(), player.getUserId());
            if (null == userData) {
                initUserData();
            } else {
                userData.setProcess(checkCombUnlock().size());
            }
        }
        return true;
    }

    @Override
    public boolean afterLoadData() {
        return true;
    }

    @Override
    public boolean saveData() {
        if (null != userData) {
            if (userData.isInsertOption()) {
                XiaowuRecallBusiness.addXiaowuRecallUserData(userData);
            } else if (userData.isUpdateOption()) {
                XiaowuRecallBusiness.updateXiaowuRecallUserData(userData);
            }
        }

        return true;
    }

    @Override
    public void afterLogin() {
        syncXiaowuConfig();
        syncUserData();
    }

    public void syncUserData() {
        if (this.userData == null) {
            return;
        }
        syncPlayerData();
    }

    /**
     * 完成图片并且获取所有行列未领取奖励
     */
    public int nextPageGetAllReward() {
        XiaowuConfig xiaowuConfig = XiaowuRecallMgr.getXiaowuConfig();
        if (xiaowuConfig == null || !ActivityMgr.activityInTime(xiaowuConfig.getActivityInfo())) {
            return GameErrorCode.E_XIAOWU_RECALL_NO_OPEN;
        }
        if (null == userData) {
            return GameErrorCode.E_XIAOWU_RECALL_NO_UNLOCK;
        }

        // 领取图片中所有完成但是没有手动点领奖的行或列comb
        String singleRewardString;
        String rewardString = new String();
        Property reward = new Property();
        String cellsId = new String();
        for (Integer key : userData.getAwarded().keySet()) {                    //遍历combIdset，取出所有combid
            if (userData.getAwarded().get(key) == 0) {
                for (XiaowuRecallComb xiaowuRecallComb : xiaowuConfig.getXiaowuRecallCombList()) {
                    if (xiaowuRecallComb.getCellId() == key) {
                        int rewardPage = userData.getPage() < 9 ? userData.getPage() : 9;             //奖励页面，大于9就是9
                        singleRewardString = StringUtils.stringToStringList(xiaowuRecallComb.getRewards(), "\\|").get(rewardPage);
                        reward.addProperty(PropertyHelper.parseStringToProperty(singleRewardString));    //奖励加入property
                        if (rewardString.isEmpty()) {
                            rewardString = singleRewardString;
                        } else {
                            rewardString = String.format("%s;%s", rewardString, singleRewardString);
                        }
                        break;
                    }
                }
                userData.getAwarded().put(key, 1);              //领奖情况置位1 已领奖
                if (cellsId.isEmpty()) {                        //log的操作方块新增
                    cellsId = "" + key;
                } else {
                    cellsId = String.format("%s,%d", cellsId, key);
                }
            }
        }

        player.getModule(CurrencyModule.class).addCurrency(reward, eLogMoneyType.DouluoXiaowuRecall, eLogMoneyType.XiaowuRecallGetPageAllLineReward);     //奖励加入背包

        AutoLogMgr.add(new LogXiaowuRecallReward(xiaowuConfig.getActivityId(), userData.getUserId(), 1, userData.getPage(), cellsId, rewardString));     //log记录为领奖操作
        XiaowuRecallProto.XiaowuNextPageRespMsg.Builder builder = XiaowuRecallProto.XiaowuNextPageRespMsg.newBuilder();
        builder.setOldPage(userData.getPage());
        builder.setTurnCost(userData.getTurnCost());
        builder.setTurnScore(userData.getTurnScore());
        //完成图片,将当前轮次数据重置
        finishPicture();

        //发送回客户端
        builder.setReward(rewardString);
        builder.setData(createDataMsgBuilder(userData));
        builder.setRet(0);
        player.sendPacket(Protocol.U_XIAOWU_RECALL_GET_ALL_REWARD_AND_ADD_PAGE, builder);
        return 0;
    }

    /**
     * 旧图完成操作,userdata重置
     */
    private void finishPicture() {
        userData.setPage(userData.getPage() + 1);                      //记录大于第十张，但实际还是第十张
        int[] slices = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
        for (Integer key : userData.getAwarded().keySet()) {         //领奖次数置位0未领奖
            userData.getAwarded().put(key, 0);
        }
        userData.setSliceCondition(slices);
        userData.setTurnCost(0);
        userData.setTurnScore(0);
    }

    /**
     * 获取奖励(手动)
     */
    public int getReward(int combId) {
        XiaowuConfig xiaowuConfig = XiaowuRecallMgr.getXiaowuConfig();
        if (xiaowuConfig == null || !ActivityMgr.activityInTime(xiaowuConfig.getActivityInfo())) {
            return GameErrorCode.E_XIAOWU_RECALL_NO_OPEN;                           //活动没开
        }
        if (null == userData) {
            return GameErrorCode.E_XIAOWU_RECALL_NO_UNLOCK;                         //活动没解锁
        }
        if (userData.getAwarded().get(combId) == null) {
            return GameErrorCode.E_XIAOWU_CELL_ID_NOT_EXIST;                        //没有这个格子
        }
        if (userData.getAwarded().get(combId).equals(1)) {
            return GameErrorCode.E_XIAOWU_RECALL_REWARD_HAS_RECEIVE;                 //奖励已经领过
        }
        if (!checkCombUnlock().contains(combId)) {
            return GameErrorCode.E_XIAOWU_RECALL_COMB_NO_UNLOCK;                    //奖励还没解锁
        }
        String reward;
        for (XiaowuRecallComb xiaowuRecallComb : xiaowuConfig.getXiaowuRecallCombList()) {
            //找到当前comb
            if (xiaowuRecallComb.getCellId() == combId) {
                int rewardPage = userData.getPage() < 9 ? userData.getPage() : 9;
                //领取奖励
                reward = StringUtils.stringToStringList(xiaowuRecallComb.getRewards(), "\\|").get(rewardPage);
                //设已领奖
                Map<Integer, Integer> awardedMap = userData.getAwarded();
                awardedMap.put(combId, 1);
                userData.setAwarded(awardedMap);

                player.getModule(CurrencyModule.class).addCurrency(reward, eLogMoneyType.DouluoXiaowuRecall, eLogMoneyType.XiaowuRecallGetLineReward);
                //log
                AutoLogMgr.add(new LogXiaowuRecallReward(xiaowuConfig.getActivityId(), userData.getUserId(), 0, userData.getPage(), combId + "", reward));
                //发消息
                XiaowuRecallProto.XiaowuGetRewardRespMsg.Builder builder = XiaowuRecallProto.XiaowuGetRewardRespMsg.newBuilder();
                builder.setReward(reward);
                builder.setRet(0);
                builder.setUserData(createDataMsgBuilder(userData));
                player.sendPacket(ClientProtocol.U_XIAOWU_RECALL_GET_REWARD, builder);
                return 0;
            }
        }

        return 0;
    }

    /**
     * 抽取到新的cell之后，计算返回新完成的comb，用于增加进度和魂
     */
    private List<Integer> checkNewComb(int newCellId) {
        XiaowuConfig xiaowuConfig = XiaowuRecallMgr.getXiaowuConfig();
        List<Integer> newCombList = new ArrayList<>();
        //查找出新增的combo,如果是本次抽到的新格子导致的加入新增列表
        for (int i = 0; i < xiaowuConfig.getRowSliceComb().size(); i++) {       //查看行新增comb
            List<Integer> sliceList = xiaowuConfig.getRowSliceComb().get(i).getComb();
            if (sliceList.contains(newCellId)) {
                if (getUnlockSlice().containsAll(sliceList)) {
                    newCombList.add(xiaowuConfig.getRowSliceComb().get(i).getCellId());
                    break;
                }
            }
        }
        for (int i = 0; i < xiaowuConfig.getColSliceComb().size(); i++) {       //查看列新增comb
            List<Integer> combList = xiaowuConfig.getColSliceComb().get(i).getComb();
            if (combList.contains(newCellId)) {
                if (getUnlockSlice().containsAll(combList)) {
                    newCombList.add(xiaowuConfig.getColSliceComb().get(i).getCellId());
                    break;
                }
            }
        }
        return newCombList;
    }

    /**
     * 获取已解锁的comb列表
     */
    private List<Integer> checkCombUnlock() {
        XiaowuConfig xiaowuConfig = XiaowuRecallMgr.getXiaowuConfig();
        List<Integer> unlockCombList = new ArrayList<>();
        for (int i = 0; i < xiaowuConfig.getXiaowuRecallCombList().size(); i++) {
            XiaowuRecallComb xiaowuRecallComb = xiaowuConfig.getXiaowuRecallCombList().get(i);
            if (getUnlockSlice().containsAll(xiaowuRecallComb.getComb())) {
                unlockCombList.add(xiaowuRecallComb.getCellId());
            }
        }
        return unlockCombList;
    }

    /**
     * 获得已解锁格子Id的list （已转化为30001-30015）
     */
    public List<Integer> getUnlockSlice() {
        List<Integer> resultList = new ArrayList<>();
        int[] clongCondition = userData.getSliceCondition();
        for (int i = 0; i < clongCondition.length; i++) {
            if (clongCondition[i] != 0) {
                resultList.add(i + ARRAYNUM_ADD_TO_CELLID);
            }
        }
        return resultList;
    }


    /**
     * 回忆一次或十连 1-一次  2-十连
     */
    public int recall(int type) {

        XiaowuConfig xiaowuConfig = XiaowuRecallMgr.getXiaowuConfig();
        if (xiaowuConfig == null || !ActivityMgr.activityInTime(xiaowuConfig.getActivityInfo())) {
            return GameErrorCode.E_XIAOWU_RECALL_NO_OPEN;
        }
        if (null == userData) {
            return GameErrorCode.E_XIAOWU_RECALL_NO_UNLOCK;
        }
        int times;
        int realTimes = 0;
        String consume = xiaowuConfig.getPIECE_ITEM_ID() + "=";
        if (getUnlockSlice().size() == 15) {
            return GameErrorCode.E_XIAOWU_RECALL_PIC_HAS_FINISHED;      //图已经抽满了，不给抽了
        }
        if (1 == type) {
            times = 1;
            consume = consume + 1;
        } else {
            times = 10;
            consume = consume + 10;
        }
        //扣道具，不足则返回
        if (!player.getModule(CurrencyModule.class).removeCurrency(PropertyHelper.parseStringToProperty(consume), eLogMoneyType.DouluoXiaowuRecall, eLogMoneyType.XiaowuRecallCost)) {
            return GameErrorCode.E_XIAOWU_RECALL_ITEM_NO_ENOUGH;
        }
        XiaowuRecallProto.XiaowuRecallRespMsg.Builder totalBuilder = XiaowuRecallProto.XiaowuRecallRespMsg.newBuilder();

        for (int i = 0; i < times; i++) {
            //回忆单次,总消息加入抽奖一次的子消息
            totalBuilder.addSingleMsg(recallOnce());
            realTimes++;
            if (getUnlockSlice().size() == 15) {           //若抽满则返还材料
                String returnCost = xiaowuConfig.getPIECE_ITEM_ID() + "=" + (times - i - 1);
                player.getModule(CurrencyModule.class).addCurrency(PropertyHelper.parseStringToProperty(returnCost), eLogMoneyType.DouluoXiaowuRecall, eLogMoneyType.XiaowuRecallReturnCost);
                break;
            }
        }
        userData.setTurnCost(userData.getTurnCost() + realTimes);     //更新当前轮次抽奖次数
        //发送结果回客户端
        totalBuilder.setTimes(realTimes);
        totalBuilder.setRet(0);
        totalBuilder.setUserData(createDataMsgBuilder(userData));
        player.sendPacket(ClientProtocol.U_XIAOWU_RECALL, totalBuilder);
        return 0;
    }

    /**
     * 回忆一次
     */
    public XiaowuRecallProto.XiaowuRecallSingleMsg.Builder recallOnce() {
        XiaowuConfig xiaowuConfig = XiaowuRecallMgr.getXiaowuConfig();

        int[] sliceCondition = userData.getSliceCondition();        //当前格子状态

        String reward = "";
        String logUnlock = new String();
        int score = 0;
        int soulGot = 0;

        XiaowuRecallProto.XiaowuRecallSingleMsg.Builder recallResp = XiaowuRecallProto.XiaowuRecallSingleMsg.newBuilder();

        //随机一个数0-14 十五选一
        Random random = new Random();
        int randomNum = random.nextInt(15);

        //如果抽满配置的最大次数还没有出新的格子，则随机一个新格子出来
        if (sliceCondition[randomNum] > 0 && (userData.getCommonTimes() + 1) >= xiaowuConfig.getMAXTIME()){
            List<Integer> lockSliceList= new ArrayList<>();
            //取出未解锁格子
            for (int i=0;i<sliceCondition.length;i++){
                if (sliceCondition[i]==0){
                    lockSliceList.add(i);
                }
            }
            randomNum = lockSliceList.get(random.nextInt(lockSliceList.size()));
            userData.setCommonTimes(0);
        }

        //加积分,积分入库
        for (int i = 0; i < xiaowuConfig.getSingleSliceComb().size(); i++) {
            XiaowuRecallComb singleComb = xiaowuConfig.getSingleSliceComb().get(i);
            if (singleComb.getCellId() == randomNum + ARRAYNUM_ADD_TO_CELLID) {             //如果格子id对应
                //获取奖励
                reward = singleComb.getRewards();
                String[] scoreReward = reward.split("=");
                score = StringUtils.string2intSafe(scoreReward[1], 30);
                userData.setScore(userData.getScore() + score);            //加积分
                userData.setTurnScore(userData.getTurnScore() + score);     //加积分
                player.getModule(CurrencyModule.class).addCurrency(xiaowuConfig.getSCORE_ITEM_ID() + "=" + score, eLogMoneyType.DouluoXiaowuRecall, eLogMoneyType.XiaowuRecallRecallReward);

                player.notifyListener(eGamePlayerEventType.XiaowuRecallRank.getValue(), userData.getScore());
            }
        }
        //获得新残片进行特殊处理
        if (sliceCondition[randomNum] == 0) {
            sliceCondition[randomNum]++;
            userData.setSliceCondition(sliceCondition);
            //判断是否有新的comb解锁,是否因为comb解锁到达设定而获得魂，只在获得新残片时判断
            List<Integer> newCombList = checkNewComb(randomNum + ARRAYNUM_ADD_TO_CELLID);
            recallResp.addAllUnlockComb(newCombList);                   //返回新解锁的combId给总方法

            for (int i = 0; i < xiaowuConfig.getMEMORY_LEVEL().size(); i++) {
                if ((checkCombUnlock().size() - newCombList.size()) < xiaowuConfig.getMEMORY_LEVEL().get(i)         //获得前小于阈值,获得后大于阈值就得到魂
                        && checkCombUnlock().size() >= xiaowuConfig.getMEMORY_LEVEL().get(i)
                ) {
                    soulGot++;
                    userData.setSoul(userData.getSoul() + 1);
                    BigDecimal bigDecimal = BigDecimal.valueOf(userData.getSoul());
                    player.notifyListener(eGamePlayerEventType.XiaowuRecallSoulTask.getValue(), bigDecimal);
                }
            }
            userData.setCommonTimes(0);                     //设置保底为0次
        } else {
            sliceCondition[randomNum]++;
            userData.setSliceCondition(sliceCondition);
            userData.setCommonTimes(userData.getCommonTimes() + 1);
        }

        //解锁combid不为空的话加入log
        if (!recallResp.getUnlockCombList().isEmpty()) {
            for (int unlockNum : recallResp.getUnlockCombList()) {
                if (logUnlock.isEmpty()) {
                    logUnlock = "" + unlockNum;
                } else {
                    logUnlock = String.format("%s,%d", logUnlock, unlockNum);
                }
            }
        }

        AutoLogMgr.add(new LogXiaowuRecallDraw(xiaowuConfig.getActivityId(), userData.getUserId(), userData.getScore() - score, score, userData.getScore(), randomNum + ARRAYNUM_ADD_TO_CELLID, userData.getSoul() - soulGot, soulGot, userData.getSoul(), logUnlock));

        //返回给总回忆方法
        recallResp.setCellId(randomNum + ARRAYNUM_ADD_TO_CELLID);       //返回定位方格
        recallResp.setRewardScore(reward);                  //返回奖励
        recallResp.setSoulGot(soulGot);                     //返回获得魂数


        return recallResp;
    }

    /**
     * 初始化用户数据
     */

    public synchronized void initUserData() {
        //系统未解锁
        XiaowuConfig xiaowuConfig = XiaowuRecallMgr.getXiaowuConfig();
        if (!SystemOpenMgr.systemOpen(player, eSystemId.XiaowuRecall.getValue())) {
            return;
        }
        //无活动
        ActivityInfo activityInfo = XiaowuRecallMgr.getActivityInfo();
        if (!ActivityMgr.activityInShowTime(activityInfo)) {
            return;
        }
        if (userData == null || (userData.getActivityId() != activityInfo.getActivityId())) {
            XiaowuRecallUserData tmpUserData = new XiaowuRecallUserData();
            tmpUserData.setActivityId(activityInfo.getActivityId());
            tmpUserData.setUserId(player.getUserId());
            int[] slices = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};//15个方块的解锁次数
            tmpUserData.setSliceCondition(slices);
            tmpUserData.setScore(0);
            tmpUserData.setCommonTimes(0);
            tmpUserData.setSoul(0);
            tmpUserData.setPage(0);                         //页数从0到9十张,后面按9处理
            tmpUserData.setTurnCost(0);
            tmpUserData.setTurnScore(0);
            Map<Integer, Integer> tmpRewardMap = new ConcurrentHashMap<>();
            for (int i = 0; i < xiaowuConfig.getColSliceComb().size(); i++) {
                tmpRewardMap.put(xiaowuConfig.getColSliceComb().get(i).getCellId(), 0);
            }
            for (int i = 0; i < xiaowuConfig.getRowSliceComb().size(); i++) {
                tmpRewardMap.put(xiaowuConfig.getRowSliceComb().get(i).getCellId(), 0);
            }
            tmpUserData.setAwarded(tmpRewardMap);
            tmpUserData.setInsertOption();
            userData = tmpUserData;

            //个人排行榜和魂更新

            player.notifyListener(eGamePlayerEventType.XiaowuRecallRank.getValue(), userData.getScore());
            player.notifyListener(eGamePlayerEventType.XiaowuRecallSoulTask.getValue(), new BigDecimal(userData.getSoul()));
        }
    }

    private void syncXiaowuConfig() {
        XiaowuConfig xiaowuConfig = XiaowuRecallMgr.getXiaowuConfig();
        if (xiaowuConfig != null && ActivityMgr.activityInShowTime(xiaowuConfig.getActivityInfo())) {
            XiaowuRecallProto.SyncXiaowuConfigRespMsg.Builder configRespMsg = XiaowuRecallPb.parseXiaowuConfigRespMsg(xiaowuConfig, player.getLanguage());
            player.sendPacket(ClientProtocol.U_XIAOWU_RECALL_SYNC_CONFIG, configRespMsg);
        }
    }

    private void syncPlayerData() {
        if (this.userData == null) {
            return;
        }
        XiaowuRecallProto.XiaowuDataSyncMsg.Builder syncMsgBuilder = XiaowuRecallProto.XiaowuDataSyncMsg.newBuilder();
        if (null == XiaowuRecallMgr.getActivityInfo()) {
            return;
        }
        syncMsgBuilder.setActivityId(XiaowuRecallMgr.getActivityInfo().getActivityId());
        syncMsgBuilder.setUserData(createDataMsgBuilder(userData));
        player.sendPacket(Protocol.U_XIAOWU_RECALL_SYNC_DATA, syncMsgBuilder);
    }

    public int sendPlayerData() {
        if (userData == null) {
            return GameErrorCode.E_XIAOWU_RECALL_NO_UNLOCK;
        }
        XiaowuRecallProto.XiaowuRecallGetDataRespMsg.Builder dataBuilder = XiaowuRecallProto.XiaowuRecallGetDataRespMsg.newBuilder();
        dataBuilder.setRet(0);
        dataBuilder.setUserData(createDataMsgBuilder(userData));
        player.sendPacket(Protocol.U_XIAOWU_RECALL_SEND_DATA, dataBuilder);
        return 0;
    }

    /**
     * 系统解锁
     */
    public void initSystem() {
        if (null == userData) {
            initUserData();
        }
    }

    public XiaowuRecallUserData getUserData() {
        return userData;
    }
}
